package com.example.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.example.mapper.RoleMapper;
import com.example.pojo.Menu;
import com.example.mapper.MenuMapper;
import com.example.service.IMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.util.EasyExcelGenerator;
import com.example.util.JwtTokenUtil;
import com.example.util.SystemRole;
import com.example.vo.excel.MenuExcelVo;
import com.example.vo.ResultVo;
import com.example.vo.respvo.MenuAuthenticationVo;
import com.example.vo.respvo.Option;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author wsl
 * @since 2022-03-27
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Value("${jwt.tokenHeader}")
    private String tokenHeader;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private RoleMapper roleMapper;

    @Override
    public ResultVo getMenus(String menuName, Integer enabled) {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        List<Menu> menus = baseMapper.selectMenus(menuName,enabled);
        return ResultVo.response(menus);
    }

    @Override
    @Transactional
    public void importMenus(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(), MenuExcelVo.class, new AnalysisEventListener<MenuExcelVo>() {
                @Override
                public void invoke(MenuExcelVo menuVo, AnalysisContext analysisContext) {
                    Menu menu = new Menu();
                    BeanUtils.copyProperties(menuVo,menu);
                    baseMapper.insert(menu);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext analysisContext) {

                }
            }).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void exportMenus(HttpServletRequest request, HttpServletResponse response) {
        //查询数据库
        List<Menu> menus = baseMapper.selectList(null);
        List<MenuExcelVo> menuVoList = new ArrayList<MenuExcelVo>();
        menus.forEach(menu ->{
            MenuExcelVo menuVo = new MenuExcelVo();
            BeanUtils.copyProperties(menu,menuVo);
            menuVoList.add(menuVo);
        });
        EasyExcelGenerator.write(response,"menu", MenuExcelVo.class,"菜单表",menuVoList);
    }

    @Override
    public ResultVo getUserMenus(HttpServletRequest request) {
        String userId = jwtTokenUtil.getUserIdFormToken(request);
        List<Integer> roles = roleMapper.selectUserAssignedRoles(userId);
        List<Menu> menus = null;
        if(roles.contains(1)){//拥有超级管理员权限可直接查看所有菜单
            menus = baseMapper.selectAllUserRoleMenus(0);
        }else{
            menus = baseMapper.selectUserRoleMenus(userId,0);
        }
        return ResultVo.response(menus);
    }

    @Override
    public List<MenuAuthenticationVo> getMenuAuthentications() {
        return baseMapper.selectMenuAuthentication();
    }

    @Override
    public List<Menu> getNotRequireAuthMenus() {
        return getMenusByRequireAuth(0);
    }

    @Override
    public List<Menu> getRequireAuthMenus() {
        return getMenusByRequireAuth(1);
    }

    public List<Menu> getMenusByRequireAuth(int isRequireAuth){
        QueryWrapper<Menu> wrapper = new QueryWrapper<Menu>().select("path").eq("requireAuth", isRequireAuth);
        return baseMapper.selectList(wrapper);
    }

    @Override
    public List<String> getMenusWithRole(List<String> menus) {
        List<String> roles = baseMapper.selectMenusWithRole(menus);
        if(roles.size()==0){
            roles.add(SystemRole.ROLE_NO_ASSIGNED);
        }
        return roles;
    }

    @Override
    public ResultVo getMenuOptions() {
        List<Option> menus = baseMapper.selectMenuOptions(0);
        return ResultVo.response(menus);
    }

    @Override
    public ResultVo getFontMenus() {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.in("type",0,1)//菜单
                .orderByAsc("sort");
        List<Menu> menus = baseMapper.selectList(wrapper);
        return ResultVo.response(menus);
    }

    @Override
    public boolean hasSameMenuPath(Integer id, String path) {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.eq("path",path)
                .eq("deleted",0)
                .notIn(id!=null,"id",id);
        Long count = baseMapper.selectCount(wrapper);
        return count > 0;
    }

    @Override
    public boolean isDisabled(String path) {
        Menu menu = baseMapper.selectOne(new QueryWrapper<Menu>().eq("path", path));
        return menu.getEnabled() == 0;
    }

    @Override
    public boolean isSysMenu(String path) {
        Menu menu = baseMapper.selectOne(new QueryWrapper<Menu>().eq("path", path));
        return menu!=null;
    }

    @Override
    public boolean hasSameNameSiblingMenu(Integer id, String menuName, Integer parentId) {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.eq("menu_name",menuName)
                .eq("parent_id",parentId)
                .notIn(id!=null,"id",id);
        Long aLong = baseMapper.selectCount(wrapper);
        return aLong > 0;
    }

    @Override
    @Transactional
    public ResultVo updateMenu(Menu menu) {
        LambdaUpdateWrapper<Menu> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Menu::getId,menu.getId())
                .set(menu.getIconId()==null,Menu::getIconId,menu.getIconId());
        int update = baseMapper.update(menu, wrapper);
        return update>0 ? ResultVo.ok("修改成功") : ResultVo.error("修改失败!");
    }

    @Override
    @Transactional
    public ResultVo deleteMenu(Integer[] ids) {
        if(baseMapper.deleteBatchIds(Arrays.asList(ids)) > 0){
            return ResultVo.ok();
        }
        return ResultVo.error();
    }
}
